Karate has a reputation as an API testing tool, but Benjamin Bischoff shows it goes much further. In this Testomat.io meetup on writing API tests with Karate, he walks through the Karate framework end to end: Karate API testing, UI testing, mocking, visual checks, and performance. Here’s a recap of how Karate handles software testing across all these layers with very little code.
What is the Karate framework?
Karate is an open-source framework for API testing, UI testing, and performance testing. It uses simple Gherkin syntax, so you write Karate tests without separate glue code.
Karate uses a readable syntax known as Gherkin, familiar from Behavior-Driven Development (BDD), built on Given, When, and Then:
- Given sets up the test.
- When is the action you perform.
- Then is where you check results and run assertions.
What makes Karate unique is that it removes the need for glue code. In other BDD frameworks you write separate code to connect the English-language steps to the programming code. Karate has that built in.
Key features of the Karate framework
- Built-in parallel runs. Parallel execution ships in the base framework, with no add-ons.
- Java and JavaScript interoperability. You can extend the framework with Java or JavaScript.
- JSON focus. Everything is treated as JSON. Other formats like XML are converted internally, so the same assertions work across data types.
Running a simple Karate API test
API tests are Karate’s core strength. A scenario lives in a feature file. You set the endpoint with the url keyword, and can use * instead of Gherkin keywords to keep it concise.
method getto retrieve data.method postto send data.method putto update data.
Karate stores the response in a response variable and the status in response status. Use match to assert the status, for example that it equals 200 for a successful request.
Configuring and reusing data
Using the configuration file
A standard project uses karate-config.js, which returns a JavaScript object that acts as your configuration:
{
baseUrl: 'http://your-app-url.com'
}
Any parameter defined here is available in all scenarios, so you can reuse variables like baseUrl across feature files.
Capturing and manipulating API data
Save response data into a custom variable, then use JSON Path to extract fields:
* def products = response
* def onlyTheNames = get products[*].name
This selects the name property from every element and stores an array of names, which is key when you combine API data with UI testing.
Going further with UI testing
Karate is not limited to API calls. It runs UI tests in real browsers, similar to Playwright or Selenium. Configure a web driver (Chrome is a common default) and open a page:
* driver baseUrl
Target elements with CSS selectors, IDs, link text, XPath, or custom attributes. Save complex locators into variables, act on them, and assert:
* def checkoutButton = locate('#data-test-checkout')
* click checkoutButton
* match checkoutButton.text == 'Total: $19'
* wait for '.modal-content'
Combining API and UI tests for end-to-end coverage
The most powerful pattern mixes API calls and UI actions in one scenario, confirming that backend data is shown correctly on the front end. When the UI filters the raw API response, filter the API data first to keep results deterministic:
* def filteredProductNames = function(products) {
return products.filter(function(product) {
return !product.name.startsWith('discounted');
}).map(function(product) { return product.name; });
}
Then locate all UI elements, build an array of their visible text, and assert it against the filtered API names:
* def productsWebElements = locateAll('h4')
* def productNamesWeb = []
* for (var i = 0; i < productsWebElements.length; i++) {
karate.appendTo(productNamesWeb, productsWebElements[i].text.trim())
}
* match productNamesWeb == filteredProductNames
Mocking APIs for deterministic testing
Testing against live APIs that change or return unpredictable data leads to flaky results. Mocking lets you define your own responses using the same Gherkin syntax.
- Define the mock feature. Create a feature file with custom response data and an
@ignoretag so Karate treats it as a mock, not a test. - Define conditions. A scenario acts as a filter for when the mock applies, for example path
/list.jsonwith methodget. - Define the response. Set the
responsevariable to your data.
Karate includes a local mock server. Start it with karate.start, point your app at the returned localhost port, and you can even intercept browser requests so a live front end loads your mock data:
* driver intercept 'pattern-for-json' 'path-to-mock-feature'
Visual testing and screenshot comparison
Visual testing compares a current screenshot against a saved baseline image, which is faster for large tables or complex layouts. Set a fixed viewport, capture the current state, and use compare image against the baseline. On a pixel difference the test fails, and the report overlays the changed areas.
Performance testing with minimal code
Every Karate test can double as a performance test through the built-in Gatling bridge. Add the Karate Gatling dependency and the Gatling Maven plugin, write a small Java simulation class pointing at your feature file, and set the load, for example 100 simulated users over 10 seconds. Gatling then reports request counts, distribution over time, and the share of successful (200) responses.
Conclusion
Karate is far more powerful than just an API testing tool. It gives you one unified framework for work that usually needs several separate tools, with very little code:
- API tests for backend functionality.
- UI tests for browser interaction and validation.
- Combined tests so data flows correctly from API to UI.
- API mocks for reliable, deterministic data.
- Visual testing for layout and pixel changes.
- Performance tests via Gatling for load capacity.
Manage your Karate API tests, manual cases, and reports in one workspace with Testomat.io.